package com.csjy.migration.hnnd.business;

import com.csjy.migration.hnnd.*;
import com.csjy.migration.hnnd.annotation.BusinessDataConverter;
import com.csjy.migration.hnnd.dict.Bank;
import com.csjy.migration.hnnd.dict.RepayType;

import javax.script.ScriptException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@BusinessDataConverter(
    auto = false,
    insertSql = "INSERT INTO ND_BPM_RESPONSIBILITY_LOAN\n" +
        "(ID, CREATE_NAME, CREATE_BY,CREATE_DATE,  UPDATE_NAME, UPDATE_BY, UPDATE_DATE, SYS_ORG_CODE, SYS_COMPANY_CODE, BPM_STATUS, PRO_ID, PRO_TYPE, BANK, REPAY_RATE_MONTH, BANK_NAME, PAY_MONEY, PAY_DATE, REPAY_TYPE, ANNUAL_PREMIUM, END_DATE, MANAGER_A, MANAGER_B, MANAGER_C, GURANT_TYPE, GURANT_FILE, CREDIT_FILE, CUSTOM_BANK, PAY_ACCOUNT_NO, CHECK_SIGN, REPAY_PLAN, PAY_VOUCHER, VOUCHER_FILE_ID, ACCOUNT_REMARK, TOBERELIEVED_MONEY, APPLICATION_APPROVAL_TYPE, GUARANT_AGREE_NO, GUARANTEE_CONTRACT_NO, PAY_ANNUALLY, MAX_GUARANTEE_CONTRACT, NOTICE_OF_PAYMENT, LOAN_CONTRACT_NUMBER, ANNUAL_INTEREST_RATE, CUSTOMER_LOAN_ACCOUNT, LOAN_NUMBER, IS_VALID, TASK_ID, PROC_ID, TASK_DEF_KEY, SOURCE_ID)\n" +
        "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
    updateSql = "UPDATE ND_BPM_RESPONSIBILITY_LOAN\n" +
        "SET CREATE_NAME=?, CREATE_BY=?, CREATE_DATE=?,UPDATE_NAME=?, UPDATE_BY=?, UPDATE_DATE=?,SYS_ORG_CODE=?, SYS_COMPANY_CODE=?, BPM_STATUS=?,   PRO_ID=?, PRO_TYPE=?, BANK=?, REPAY_RATE_MONTH=?, BANK_NAME=?, PAY_MONEY=?, PAY_DATE=?, REPAY_TYPE=?, ANNUAL_PREMIUM=?, END_DATE=?, MANAGER_A=?, MANAGER_B=?, MANAGER_C=?, GURANT_TYPE=?, GURANT_FILE=?, CREDIT_FILE=?, CUSTOM_BANK=?, PAY_ACCOUNT_NO=?, CHECK_SIGN=?, REPAY_PLAN=?, PAY_VOUCHER=?, VOUCHER_FILE_ID=?, ACCOUNT_REMARK=?, TOBERELIEVED_MONEY=?, APPLICATION_APPROVAL_TYPE=?, GUARANT_AGREE_NO=?, GUARANTEE_CONTRACT_NO=?, PAY_ANNUALLY=?, MAX_GUARANTEE_CONTRACT=?, NOTICE_OF_PAYMENT=?, LOAN_CONTRACT_NUMBER=?, ANNUAL_INTEREST_RATE=?, CUSTOMER_LOAN_ACCOUNT=?, LOAN_NUMBER=?, IS_VALID=?, TASK_ID=?, PROC_ID=?, TASK_DEF_KEY=?, SOURCE_ID=?\n" +
        "WHERE ID = ?",
    findMigratedIdListSql = "SELECT ID FROM ND_BPM_RESPONSIBILITY_LOAN WHERE PROC_ID = ?"
)
public class NdBpmResponsibilityLoan extends AbstractWorkflowBusiness {

  private boolean filterByWorkflow = true;
  public NdBpmResponsibilityLoan(DbUtil sourceDbUtil, DbUtil targetDbUtil, SourceBusinessData sourceData, ProgramArgument programArgument, String projectId, String procInstId) throws SQLException {
    super(sourceDbUtil, targetDbUtil, sourceData, programArgument, projectId, procInstId);
  }
  public NdBpmResponsibilityLoan(DbUtil sourceDbUtil, DbUtil targetDbUtil
          , SourceBusinessData sourceData, ProgramArgument programArgument,
                                 String projectId, String procInstId, boolean filterByWorkflow) throws SQLException {
    super(sourceDbUtil, targetDbUtil, sourceData, programArgument, projectId, procInstId);
    this.filterByWorkflow = filterByWorkflow;
  }

  @Override
  public void migrate() throws Exception {
    List<Map> btItemAccountDetailList = this.sourceData.getBtItemAccountDetailList().stream()
        .filter(btItemAccountDetail->{
          if(this.filterByWorkflow) {
            String workflowNo = btItemAccountDetail.get("WORKFLOWNO") == null
                    ? null : btItemAccountDetail.get("WORKFLOWNO").toString();
            return workflowNo.equals(this.procInstId) && btItemAccountDetail.get("ACCOUNTTYPE").toString().equals("1");
          } else {
            return btItemAccountDetail.get("ACCOUNTTYPE").toString().equals("1");
          }
        })
        .collect(Collectors.toList());
    for(Map.Entry<String,Map<String,Object>> entry : taskParamMap.entrySet()) {
      String curJbpmTaskInstanceId = entry.getKey();
      Map<String,Object> taskParam = entry.getValue();

      for (Map row : btItemAccountDetailList) {
        try {
          // 判断是否需要覆盖迁移
          int needMigratedResult = this.needMigrated(row.get("ACCOUNTNO").toString()+"-"+curJbpmTaskInstanceId);
          if(needMigratedResult == 0) {
            continue;
          }

          // 单条插入或更新
          if(needMigratedResult == 1) {
            this.targetDbUtil.updateByParams(updateSql,this.buildValues(row, curJbpmTaskInstanceId, taskParam),true);
            // 批量插入或更新 和 单条插入或更新 二选一
//            this.batchUpdateValues.add(this.buildValues(row, curJbpmTaskInstanceId, taskParam));
          } else {
            this.targetDbUtil.updateByParams(insertSql,this.buildValues(row, curJbpmTaskInstanceId, taskParam));
            // 批量插入或更新 和 单条插入或更新 二选一
//            this.batchInsertValues.add(this.buildValues(row, curJbpmTaskInstanceId, taskParam));
          }
        } catch(Exception e) {
          throw new Exception(String.format("流程实例[%s]-任务实例[%s]-放款数据迁移失败:%s\n",this.procInstId, curJbpmTaskInstanceId, e.getMessage()));
        }
      }
    }
  }

  public List buildValues(Map row, String curJbpmTaskInstanceId, Map<String,Object> taskParam) throws ScriptException, SQLException {
    List values = new ArrayList();
    // ID
    values.add(row.get("ACCOUNTNO")+"-"+curJbpmTaskInstanceId);
    // CREATE_NAME
    values.add(null);
    // CREATE_BY
    values.add(null);
    // CREATE_DATE
    values.add(row.get("CREATE_TIME"));
    // UPDATE_NAME
    values.add(null);
    // UPDATE_BY
    values.add(null);
    // UPDATE_DATE
    values.add(row.get("MODIFY_TIME"));
    // SYS_ORG_CODE
    values.add(null);
    // SYS_COMPANY_CODE
    values.add("002");
    // BPM_STATUS
    values.add(1);
    //  PRO_ID	项目ID
    values.add(this.projectId);
    // 		账目类型
    values.add(row.get("ACCOUNTTYPE"));
    //  TODO: BANK		合作银行 字典
    values.add(DictTool.getTargetDictCode(Bank.class,row.get("BANKID")));
    //  REPAY_RATE_MONTH		还款月利率
    values.add(row.get("MONTHRATE"));
    //  BANK_NAME		支行名称
    values.add(row.get("BANKBRANCH"));
    //  PAY_MONEY	放款额|万
    values.add(row.get("OCCURSUM"));
    //  PAY_DATE		放款时间
    values.add(row.get("OCCURTIME"));
    //  REPAY_TYPE		还款方式
    values.add(sourceData.getRepayType());
    //  ANNUAL_PREMIUM		按年付保费
    values.add(row.get("ASSFAREWAY"));
    //  END_DATE		到期时间
    values.add(row.get("ENDTIME"));
    //  MANAGER_A		责任经理A
    values.add(row.get("MANAGERA"));
    //  MANAGER_B		责任经理B
    values.add(row.get("MANAGERB"));
    //  MANAGER_C		责任经理C
    values.add(row.get("MANAGERC"));
    //  TODO: GURANT_TYPE		担保品种 字典
    values.add(row.get("ASSURECLASS"));
    //  GURANT_FILE		保证合同
    values.add(row.get("PROMCONTRACTNO"));
    //  CREDIT_FILE	 贷款合同
    values.add(row.get("LOANCONTRACTNO"));
    //  CUSTOM_BANK	 客户开户行
    values.add(DictTool.getTargetDictCode(Bank.class,row.get("CLIENTBANKID")));
    //  PAY_ACCOUNT_NO	放款账号
    values.add(row.get("OCCURACCOUNT") == null ?  row.get("CLIENTBANKACCOUNT") : row.get("OCCURACCOUNT"));
    //  CHECK_SIGN	核实标记
    values.add(row.get("CHECKFLAG") == null ? 0 : Integer.parseInt(row.get("CHECKFLAG").toString()) - 1);
    //  TODO:REPAY_PLAN	还款计划
    values.add(row.get("PLANFLAG"));
    //  PAY_VOUCHER	放款凭证
    values.add(row.get("ELEFILENAME"));
    //  VOUCHER_FILE_ID	放款凭证附件ID
    values.add(row.get("ELEFILESTORENAME") == null ? null : row.get("ELEFILESTORENAME").toString().replace("-",""));
    //  ACCOUNT_REMARK	账目备注 原始备注 + 还款方式 + 还款计划
    String accountRemark = row.get("ACCOUNTMEMO") == null ? "" : Tool.decodeUnicode(row.get("ACCOUNTMEMO").toString());
    accountRemark = accountRemark
        +"\n\n老系统其他字段信息"
        + "\n还款方式："+ row.get("RETURNWAY") + "-" + BusinessTool.getOldDictDataNameByDictCodeAndDataCode("35",row.get("RETURNWAY"))
        + " \n还款计划："+ row.get("PLANFLAG") + "-" + BusinessTool.getOldDictDataNameByDictCodeAndDataCode("46",row.get("PLANFLAG"))
        + " \n还款月利率："+ row.get("MONTHRATE");
    values.add(accountRemark);
    //  TOBERELIEVED_MONEY	待解除额 动态计算
    values.add(this.getToBeRelieveMoney(row.get("ACCOUNTNO").toString()));
    //  TODO:APPLICATION_APPROVAL_TYPE	申请审批类型
    values.add(null);
    //  GUARANT_AGREE_NO		担保协议编号
    values.add(this.sourceData.getBtItemBasic().get(0).get("ASSUCONTRACTNO"));
    //  TODO:GUARANTEE_CONTRACT_NO	保证合同编号
    values.add(null);
    //  PAY_ANNUALLY	按年支付担保费
    values.add(row.get("ASSFAREWAY"));
    //  TODO:MAX_GUARANTEE_CONTRACT	最高额度保证合同
    values.add(null);
    // TODO: NOTICE_OF_PAYMENT	凭放用款通知书
    values.add(null);
    //  TODO:LOAN_CONTRACT_NUMBER	贷款合同编号 = LOANCONTRACTNO ?
    values.add(null);
    //  ANNUAL_INTEREST_RATE	年利率
    values.add(row.get("YEARRATE"));
    //  CUSTOMER_LOAN_ACCOUNT	客户放款账号
    values.add(row.get("CLIENTBANKACCOUNT"));
    //  LOAN_NUMBER		放款编号
    values.add(row.get("ACCOUNTNO"));
    //  IS_VALID	是否使用
    values.add("Y");
    //  TASK_ID	任务ID
    values.add(curJbpmTaskInstanceId + "-JW");
    //  PROC_ID	流程ID
    values.add(this.procInstId + "-JW");
    //  TASK_DEF_KEY	节点ID
    values.add(taskParam.get("taskDefKey"));
    //  SOURCE_ID		业务ID
    values.add(row.get("ACCOUNTNO"));

    return values;
  }

  // 获取 待解除金额
  public Object getToBeRelieveMoney(String accountNo) throws SQLException {
    String sql = "\n" +
        "    SELECT a.occurSum - (\n" +
        "        (\n" +
        "            SELECT nvl(sum(t.occurSum), 0)\n" +
        "    FROM bt_item_account_detail t\n" +
        "    WHERE t.itemNo = a.itemNo\n" +
        "    AND t.loanAccountNo = a.accountNo\n" +
        "    AND t.accountType = 2\n" +
        "\t\t)\n" +
        "    +\n" +
        "        (\n" +
        "            SELECT nvl(sum(t.occurSum), 0)\n" +
        "    FROM bt_item_instead_account_detail t\n" +
        "    WHERE t.itemNo = a.itemNo AND t.loanAccountNo = a.accountNo\n" +
        "\t\t)\n" +
        "\t) assurSum FROM BT_ITEM_ACCOUNT_DETAIL a\n" +
        "    WHERE a.ACCOUNTNO = '" + accountNo + "'\n" ;
    List<Map> list = this.sourceDbUtil.selectByParams(sql, new ArrayList());
    if(list.size() == 0) {
      return null;
    }
    return list.get(0).get("assurSum");
  }

}
